#include "rf433.h"
#include "gd32e23x_it.h"
#include "systick.h"
#include "config.h"
#include "sub_device.h"

//#define  USE_SPI_CONTROLLER

#define KEY_GROUP1_1       0X1
#define KEY_GROUP1_2       0X2
#define KEY_GROUP2_1       0X4
#define KEY_GROUP2_2       0X8
#define KEY_GROUP3_1       0X10
#define KEY_GROUP3_2       0X20

#define PANEL_KEY_UP       0xC0


#define SYSTEMCLOCK_REG 	0x00
#define PLL1_REG 			0x01
#define PLL2_REG 			0x02
#define PLL3_REG 			0x03
#define PLL4_REG			0x04
#define PLL5_REG			0x05
#define PLL6_REG			0x06
#define CRYSTAL_REG			0x07
#define PAGEA_REG	  		0x08
#define PAGEB_REG			0x09
#define RX1_REG  			0x0A
#define RX2_REG  			0x0B
#define ADC_REG  			0x0C
#define PIN_REG 			0x0D
#define CALIBRATION_REG  		0x0E
#define MODE_REG  			0x0F

#define TX1_PAGEA           0x00
#define WOR1_PAGEA          0x01
#define WOR2_PAGEA          0x02
#define RFI_PAGEA           0x03
#define PM_PAGEA            0x04
#define RTH_PAGEA           0x05
#define AGC1_PAGEA          0x06
#define AGC2_PAGEA          0x07
#define GIO_PAGEA           0x08
#define CKO_PAGEA           0x09
#define VCB_PAGEA           0x0A
#define CHG1_PAGEA          0x0B
#define CHG2_PAGEA          0x0C
#define FIFO_PAGEA			0x0D
#define CODE_PAGEA			0x0E
#define WCAL_PAGEA			0x0F

#define TX2_PAGEB			0x00
#define	IF1_PAGEB			0x01
#define IF2_PAGEB			0x02
#define	ACK_PAGEB			0x03
#define	ART_PAGEB			0x04


#define CMD_Reg_W			0x00	//000x,xxxx	control register write
#define CMD_Reg_R			0x80	//100x,xxxx	control register read
#define CMD_ID_W			0x20	//001x,xxxx	ID write
#define CMD_ID_R			0xA0	//101x,xxxx	ID Read
#define CMD_FIFO_W			0x40	//010x,xxxx	TX FIFO Write
#define CMD_FIFO_R			0xC0	//110x,xxxx	RX FIFO Read
#define CMD_RF_RST			0x70	//0111,xxxx	RF reset
#define CMD_TFR				0x60	//0110,xxxx	TX FIFO address pointrt reset
#define CMD_RFR				0xE0	//1110,xxxx	RX FIFO address pointer reset

#define CMD_SLEEP			0x10	//0001,0000	SLEEP mode
#define CMD_IDLE			0x12	//0001,0010	IDLE mode
#define CMD_STBY			0x14	//0001,0100	Standby mode
#define CMD_PLL				0x16	//0001,0110	PLL mode
#define CMD_RX				0x18	//0001,1000	RX mode
#define CMD_TX				0x1A	//0001,1010	TX mode
//#define CMD_DEEP_SLEEP	0x1C	//0001,1100 Deep Sleep mode(tri-state)
#define CMD_DEEP_SLEEP		0x1F	//0001,1111 Deep Sleep mode(pull-high)

#define A7129_Int_Handler  EXTI4_15_IRQHandler

#define A7129_SPI0_IRQn         EXTI4_15_IRQn
#define A7129_SPI0_EXIT_SOURCE  EXTI_SOURCE_GPIOA
#define A7129_SPI0_EXIT_PIN     EXTI_SOURCE_PIN6
#define A7129_SPI0_EXIT_LINE    EXTI_6


#define A7129_MAX_FIFO_LEN        64



static volatile uint8_t rf_int_flag;
typedef struct
{
   uint32_t port;
   uint32_t pin;
}gpio_info;

#if defined(USE_SPI_CONTROLLER)

#else

#define A7129_SPI0_MOSI   2
#define A7129_SPI0_SCLK   1
#define A7129_SPI0_CS     0
#define A7129_SPI0_INT    3

gpio_info rf433_gpio[]={{GPIOA,GPIO_PIN_4},{GPIOA,GPIO_PIN_5},{GPIOA,GPIO_PIN_7},{GPIOA,GPIO_PIN_6}};


#endif

static uint8_t a7129_fifo_buf[A7129_MAX_FIFO_LEN];
static const uint8_t  ID_Tab[4]={0x54,0x21,0xA4,0x23};   //ID code
static const uint16_t  A7129Config[]=		//433MHz, 100kbps (IFBW = 100KHz, Fdev = 37.5KHz), Crystal=12.8MHz
{
	0x0021,		//SYSTEM CLOCK register,
	0x0A21,		//PLL1 register,
	0xDA05,		//PLL2 register,	433.301MHz
	0x0000,		//PLL3 register,
	0x0A20,		//PLL4 register,
	0x0024,		//PLL5 register,
	0x0000,		//PLL6 register,
	0x0011,		//CRYSTAL register,
	0x0000,		//PAGEA,
	0x0000,		//PAGEB,
	0x18D4,		//RX1 register, 	IFBW=100KHz
	0x7009,		//RX2 register, 	by preamble
	0x4000,		//ADC register,	   	
	0x0800,		//PIN CONTROL register,		Use Strobe CMD
	0x4C45,		//CALIBRATION register,
	0x20C0		//MODE CONTROL register, 	Use FIFO mode
};

static const uint16_t  A7129Config_PageA[]=   //433MHz, 100kbps (IFBW = 100KHz, Fdev = 37.5KHz), Crystal=12.8MHz
{
	0xF706,		//TX1 register, 	Fdev = 37.5kHz
	0x0000,		//WOR1 register,
	0xF800,		//WOR2 register,
	0x1107,		//RFI register, 	Enable Tx Ramp up/down  
	0x0970,		//PM register,
	0x0302,		//RTH register,
	0x400F,		//AGC1 register,	
	0x0AC0,		//AGC2 register, 
	
	0x0001,		//GIO register, 	GIO2=WTR, GIO1=FSYNC  this register config gio1 or gio2
	
	0xD181,		//CKO register
	0x0004,		//VCB register,
	0x0A21,		//CHG1 register, 	430MHz
	0x0022,		//CHG2 register, 	435MHz
	//0x0009,		//FIFO register, 	FEP=63+1=64bytes
	FIFO_DEFINE_LEN-1,
	0x1507,		//CODE register, 	Preamble=4bytes, ID=4bytes
	0x0000		//WCAL register,
};

static const uint16_t A7129Config_PageB[]=   //433MHz, 100kbps (IFBW = 100KHz, Fdev = 37.5KHz), Crystal=12.8MHz
{
	0x0337,		//TX2 register,
	0x0400,		//IF1 register, 	Enable Auto-IF, IF=200KHz
	0x0000,		//IF2 register,
	0x0000,		//ACK register,
	0x0000		//ART register,
};

static const uint16_t crc16_ccitt_table[256] = 
{
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};

void A7129_Int_Handler(void)
{
   if(RESET != exti_interrupt_flag_get(A7129_SPI0_EXIT_LINE))
   {
        printf("A7129 inteerupt\r\n");
        rf_int_flag=1;
   }
    
   exti_interrupt_flag_clear(A7129_SPI0_EXIT_LINE);
}

static inline  void set_mosi_out(void)
{
   GPIO_CTL(GPIOA)&=~((uint32_t)3<<14);
   GPIO_CTL(GPIOA)|=(uint32_t)1<<14;

   GPIO_OSPD(GPIOA)&=~((uint32_t)3<<14); //out speed 10M
   GPIO_OSPD(GPIOA)|=(uint32_t)1<<14;

   GPIO_PUD(GPIOA)&=~((uint32_t)3<<14);  //pull up
   GPIO_PUD(GPIOA)|=(uint32_t)1<<14;
   GPIO_OMODE(GPIOA)&=~((uint32_t)1<<7);  //push pull mode

}

static inline  void set_mosi_input(void)
{

   GPIO_CTL(GPIOA)&=~((uint32_t)3<<14);

   GPIO_PUD(GPIOA)&=~((uint32_t)3<<14);  // no pull up no pull down

}

static inline  void set_mosi_level(uint32_t level)
{
   if(level)
   GPIO_BOP(GPIOA)=(uint32_t)1<<7;
   else
   GPIO_BC(GPIOA)=(uint32_t)1<<7;
}

static inline  uint32_t get_mosi_level(void)
{
   return GPIO_ISTAT(GPIOA)>>7&0x1;
}

static inline  void set_clk_level(uint32_t level)
{
   if(level)
   GPIO_BOP(GPIOA)=(uint32_t)1<<5;
   else
   GPIO_BC(GPIOA)=(uint32_t)1<<5;
}

static inline  void set_cs_level(uint32_t level)
{
   if(level)
   GPIO_BOP(GPIOA)=(uint32_t)1<<4;
   else
   GPIO_BC(GPIOA)=(uint32_t)1<<4;
}


static void A7129_GpioInit(void)
{
#if defined(USE_SPI_CONTROLLER)
    spi_parameter_struct spi_init_struct;

    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_SPI0);
    /* SPI0_CLK(PA5),  SPI0_NSS(PA4), SPI0_MOSI(PA7),*/
    gpio_af_set(GPIOA, GPIO_AF_0, GPIO_PIN_5 |GPIO_PIN_7|GPIO_PIN_4);
    gpio_mode_set(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_5 |GPIO_PIN_7|GPIO_PIN_4);
    
    gpio_output_options_set(GPIOA, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4 | GPIO_PIN_5 |GPIO_PIN_7);

    gpio_mode_set(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_6);
    /* SPI0 parameter config */
    spi_init_struct.trans_mode           = SPI_TRANSMODE_BDTRANSMIT;
    spi_init_struct.device_mode          = SPI_MASTER;
    spi_init_struct.frame_size           = SPI_FRAMESIZE_8BIT;
    spi_init_struct.clock_polarity_phase = SPI_CK_PL_LOW_PH_1EDGE;
    spi_init_struct.nss                  = SPI_NSS_HARD;
    spi_init_struct.prescale             = SPI_PSC_32;
    spi_init_struct.endian               = SPI_ENDIAN_MSB;
    spi_init(SPI0, &spi_init_struct);
    spi_enable(SPI0);
#else
/* enable the  clock */
   rcu_periph_clock_enable(RCU_GPIOA);
   /* configure rf GPIO port */ 
   gpio_mode_set(rf433_gpio[A7129_SPI0_CS].port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, rf433_gpio[A7129_SPI0_CS].pin);
   gpio_output_options_set(rf433_gpio[A7129_SPI0_CS].port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, rf433_gpio[A7129_SPI0_CS].pin);
   
   gpio_mode_set(rf433_gpio[A7129_SPI0_SCLK].port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, rf433_gpio[A7129_SPI0_SCLK].pin);
   gpio_output_options_set(rf433_gpio[A7129_SPI0_SCLK].port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, rf433_gpio[A7129_SPI0_SCLK].pin);

   gpio_mode_set(rf433_gpio[A7129_SPI0_MOSI].port, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, rf433_gpio[A7129_SPI0_MOSI].pin);
   gpio_output_options_set(rf433_gpio[A7129_SPI0_MOSI].port, GPIO_OTYPE_PP, GPIO_OSPEED_10MHZ, rf433_gpio[A7129_SPI0_MOSI].pin);

   //gpio_mode_set(rf433_gpio[A7129_SPI0_INT].port, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, rf433_gpio[A7129_SPI0_INT].pin);

#endif
   /*nvic_irq_enable(A7129_SPI0_IRQn, 1U);
   syscfg_exti_line_config(A7129_SPI0_EXIT_SOURCE, A7129_SPI0_EXIT_PIN);
   exti_init(A7129_SPI0_EXIT_LINE, EXTI_INTERRUPT, EXTI_TRIG_FALLING);
   exti_interrupt_flag_clear(A7129_SPI0_EXIT_LINE);*/
}

static void SpiSendOneByte(uint8_t data)
{
   uint8_t i;
   #if defined(USE_SPI_CONTROLLER)
   
   //SPI_CTL1(SPI0) |= SPI_CTL1_BYTEN;
   while(RESET == (SPI_STAT(SPI0)&SPI_FLAG_TBE));
   SPI_DATA(SPI0) = data;

   #else
   set_mosi_out();
   for(i=0;i<8; i++)
   {
      set_clk_level(0);
      if(data&0x80)
      {
         set_mosi_level(1);
      }
      else
      {
         set_mosi_level(0);
      }
      data<<=1;
      
      set_clk_level(1);/* 器件在时钟上升沿采样数据  */
   }
   set_clk_level(0);
   #endif
}

static uint8_t SpiReadOneByte(void)
{
   uint8_t i, data=0;
   #if defined(USE_SPI_CONTROLLER)

   #else
   set_mosi_input(); 
   for(i=0; i<8; i++)
   {
      set_clk_level(0);
      data<<=1;
      
      set_clk_level(1);/* 在时钟下降沿改变数据，上升沿锁存并输出到单片机 */
      if(get_mosi_level())/* 数据位是高位在前 */
      { 
         data++;
      }
   }
   set_clk_level(0);
   #endif
   return data;
   
}

static void A7129_WriteReg(uint8_t address, uint16_t dataWord)
{
   uint8_t tmp;
   address |= CMD_Reg_W;
   set_cs_level(0);
   SpiSendOneByte(address);
   tmp = (uint8_t)(dataWord >> 8);
   SpiSendOneByte(tmp);
   tmp = (uint8_t)dataWord;
   SpiSendOneByte(tmp);
   set_cs_level(1);
}

static uint16_t A7129_ReadReg(uint8_t address)
{
   uint8_t i,j;
   uint16_t tmp;
   address |= CMD_Reg_R;
   set_cs_level(0);
   SpiSendOneByte(address);
   //read data code
   i = SpiReadOneByte();
   
   tmp = (uint16_t)i << 8;
   j = SpiReadOneByte();
   set_cs_level(1);
   tmp += j;
   return tmp;
}

/************************************************************************
**  A7129_WritePageA
************************************************************************/
static void A7129_WritePageA(uint8_t address, uint16_t dataWord)
{
    uint16_t tmp;

    tmp = address;
    tmp = ((tmp << 12) | A7129Config[CRYSTAL_REG]);
    A7129_WriteReg(CRYSTAL_REG, tmp);
    A7129_WriteReg(PAGEA_REG, dataWord);
}

/************************************************************************
**  A7129_ReadPageA
************************************************************************/
static uint16_t A7129_ReadPageA(uint8_t address)
{
    uint16_t tmp;

    tmp = address;
    tmp = ((tmp << 12) | A7129Config[CRYSTAL_REG]);
    A7129_WriteReg(CRYSTAL_REG, tmp);
    tmp = A7129_ReadReg(PAGEA_REG);
    return tmp;
}

static void A7129_StrobeCmd(uint8_t cmd)
{
   set_cs_level(0);
   SpiSendOneByte(cmd);
   set_cs_level(1);
}

/************************************************************************
**  A7129_WritePageB
************************************************************************/
static void A7129_WritePageB(uint8_t address, uint16_t dataWord)
{
    uint16_t tmp;

    tmp = address;
    tmp = ((tmp << 7) | A7129Config[CRYSTAL_REG]);
    A7129_WriteReg(CRYSTAL_REG, tmp);
    A7129_WriteReg(PAGEB_REG, dataWord);
}

/************************************************************************
**  crc compute
************************************************************************/
static uint16_t do_crc_ccitt(uint8_t *q, int16_t len)
{
    uint16_t crc = 0x1D0F;

    while (len-- > 0)
    crc = crc16_ccitt_table[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8);
    return crc;
}

static uint16_t A7129_Config(void)
{
   uint8_t i;
	  uint16_t tmp;
	  for(i=0; i<8; i++)
      A7129_WriteReg(i, A7129Config[i]);
   for(i=10; i<16; i++)
      A7129_WriteReg(i, A7129Config[i]);
   for(i=0; i<16; i++)
      A7129_WritePageA(i, A7129Config_PageA[i]);
	  for(i=0; i<5; i++)
      A7129_WritePageB(i, A7129Config_PageB[i]);
   tmp = A7129_ReadReg(SYSTEMCLOCK_REG);
   if(tmp != A7129Config[SYSTEMCLOCK_REG])
   {
       printf("A7129 config failed\r\n");
       return 1;
   }

   uint8_t fb, fcd, fbcf;	//IF Filter
  	uint8_t vb,vbcf;			//VCO Current
	  uint8_t vcb, vccf;		//VCO Band
   //IF calibration procedure @STB state
	  A7129_WriteReg(MODE_REG, A7129Config[MODE_REG] | 0x0802);			//IF Filter & VCO Current Calibration
	  do{
        tmp = A7129_ReadReg(MODE_REG);
    }while(tmp & 0x0802);

   //for check(IF Filter)
   tmp = A7129_ReadReg(CALIBRATION_REG);
   fb = tmp & 0x0F;
   fcd = (tmp>>11) & 0x1F;
   fbcf = (tmp>>4) & 0x01;
   if(fbcf)
   {
      printf("A7129 config failed-\r\n");
      return 1;
   }
   //for check(VCO Current)
   tmp = A7129_ReadPageA(VCB_PAGEA);
   vcb = tmp & 0x0F;
   vccf = (tmp>>4) & 0x01;
   if(vccf)
   {
      printf("A7129 config failed--\r\n");
      return 1;
   }
   //RSSI Calibration procedure @STB state
   A7129_WriteReg(ADC_REG, 0x4C00);									//set ADC average=64
   A7129_WriteReg(MODE_REG, A7129Config[MODE_REG] | 0x1000);			//RSSI Calibration
   do{
       tmp = A7129_ReadReg(MODE_REG);
   }while(tmp & 0x1000);
   A7129_WriteReg(ADC_REG, A7129Config[ADC_REG]);

   //VCO calibration procedure @STB state
   A7129_WriteReg(PLL1_REG, A7129Config[PLL1_REG]);
   A7129_WriteReg(PLL2_REG, A7129Config[PLL2_REG]);
   A7129_WriteReg(MODE_REG, A7129Config[MODE_REG] | 0x0004);		//VCO Band Calibration
   do{
       	tmp = A7129_ReadReg(MODE_REG);
     }while(tmp & 0x0004);

   //for check(VCO Band)
   tmp = A7129_ReadReg(CALIBRATION_REG);
   vb = (tmp >>5) & 0x07;
   vbcf = (tmp >>8) & 0x01;
   if(vbcf)
   {
      printf("A7129 config failed---\r\n");
      return 1;
   }
   printf("A7129 config success\r\n");
   return 0;
}

static uint16_t A7129_WriteId(void)
{
   uint8_t i;
   set_cs_level(0);
   SpiSendOneByte(CMD_ID_W);
   for(i=0; i<4; i++)
	    SpiSendOneByte(ID_Tab[i]);
	  set_cs_level(1);

	  
	  uint8_t d1, d2, d3, d4;
	  set_cs_level(0);
	  SpiSendOneByte(CMD_ID_R);
	  d1=SpiReadOneByte();
	  d2=SpiReadOneByte();
	  d3=SpiReadOneByte();
	  d4=SpiReadOneByte();
	  set_cs_level(1);
	  if((d1!=ID_Tab[0]) || (d2!=ID_Tab[1]) || (d3!=ID_Tab[2]) || (d4!=ID_Tab[3]))
   {
       printf("A7129 write id failed\r\n");
       return 1;
   }
   printf("A7129 write id success\r\n");
   return 0;
}

static void A7129_WriteFIFO(uint8_t *buf, uint8_t len)
{
    uint8_t i;
    uint16_t crc;
    A7129_StrobeCmd(CMD_TFR);		//TX FIFO address pointer reset
    set_cs_level(0);
    SpiSendOneByte(CMD_FIFO_W);	//TX FIFO write command
    for(i=0; i <len; i++)
    SpiSendOneByte(buf[i]);
    crc = do_crc_ccitt(buf,8);
    
    SpiSendOneByte((uint8_t)(crc>>8));
    SpiSendOneByte(crc&0xff);
    set_cs_level(1);
}



//ff-ff-0-dd-90-0-0
static uint8_t * A7129_RxPacket(uint8_t *status)
{
   uint8_t i;
   uint16_t crc_data;
   *status=1;
   A7129_StrobeCmd(CMD_RFR);		//RX FIFO address pointer reset
   set_cs_level(0);
   SpiSendOneByte(CMD_FIFO_R);
   for(i=0; i<FIFO_DEFINE_LEN; i++)
   {
      a7129_fifo_buf[i] = SpiReadOneByte(); 
   }
   set_cs_level(1);
   A7129_StrobeCmd(CMD_RFR);		//RX FIFO address pointer reset
   crc_data = do_crc_ccitt(a7129_fifo_buf,3);
   uint8_t *pt=a7129_fifo_buf;
   //gd_printf(("+++-%x-%x-%x-%x-%x-%x-%x-%x-%x-%x,crc=0x%x\r\n",pt[0],pt[1],pt[2],pt[3],pt[4],pt[5],pt[6],pt[7],pt[8],pt[9],crc_data));
   //由于历史的原因，包里有两个地方的CRC校验
   if((a7129_fifo_buf[3] == (uint8_t)(crc_data>>8))&&(a7129_fifo_buf[4] == (uint8_t)crc_data))
   {
      crc_data = do_crc_ccitt(a7129_fifo_buf,6);
      
      if((a7129_fifo_buf[6] == (uint8_t)crc_data))
      {
         /*if(PANEL_KEY_UP==a7129_fifo_buf[2])
         {
            *status=1;
         }
         else
         {
            *status=0;
         }*/
         *status=0;//动能开关
         return a7129_fifo_buf;
      }
   }
   else
   {
     crc_data = do_crc_ccitt(a7129_fifo_buf,8);
     if((a7129_fifo_buf[8]==(crc_data>>8&0xff))&&(a7129_fifo_buf[9]==(crc_data&0xff)))
     {
        //gd_printf(("crc verfiry success\r\n"));
        *status=1;//非动能开关
        return a7129_fifo_buf;
     }
     else
     {
        //gd_printf(("crc verifry failed\r\n"));
     }
     
     //DBG_8711B("A7129 recv fifo data error crc=0x%x\r\n",crc_data);
   }
   return (uint8_t *)0;
}

uint8_t *A7129_SendFrameWait(uint8_t *buf, uint8_t len)
{
   uint16_t m;
   uint8_t n=0,k;
   uint8_t *pt;
   uint8_t status;
loop:
   A7129_StrobeCmd(CMD_STBY);
   A7129_WriteReg(PLL2_REG,0xDA05);
   A7129_StrobeCmd(CMD_PLL);
   A7129_WriteFIFO(buf, len);
   A7129_StrobeCmd(CMD_TX);
   delay_1ms(3);
   A7129_WriteReg(PLL1_REG,0x0A21);
   A7129_WriteReg(PLL2_REG,0xD605);
   A7129_StrobeCmd(CMD_RX);
   k=0;   
   n++;
   while(1)
   {
      m = A7129_ReadReg(MODE_REG);
      if(!(m&0x8))
      {
         //recved data
         if((pt = A7129_RxPacket(&status))!=(uint8_t *)0)
         {
            if(status==1)
            {
               //gd_printf(("recv respond data crc ok\r\n"));
               A7129_StrobeCmd(CMD_RX);
							        return pt;
            }
            
         }
         A7129_StrobeCmd(CMD_RX);
      }
      
      if(k>10)
      {
         if(n>5)
         { 
            gd_printf(("not recv rf respond for a long time,quit\r\n"));
            return NULL;
         }
         //gd_printf(("recv respond data timeout\r\n"));
         goto loop;
      }
      k++;
      delay_1ms(2);
   }
}


void A7129_SendFrameNoWait(uint8_t *buf, uint8_t len)
{
   A7129_StrobeCmd(CMD_STBY);
   A7129_WriteReg(PLL2_REG,0xDA05);
   A7129_StrobeCmd(CMD_PLL);
   A7129_WriteFIFO(buf, len);
   A7129_StrobeCmd(CMD_TX);
   delay_1ms(3);
   A7129_WriteReg(PLL1_REG,0x0A21);
   A7129_WriteReg(PLL2_REG,0xD605);
   A7129_StrobeCmd(CMD_RX);
}


static uint16_t A7129_InitRf(void)
{
   A7129_StrobeCmd(CMD_RF_RST);
   A7129_Config();
   delay_1ms(2);			//delay 1ms for crystal stabilized
   A7129_WriteId();
   return 0;
}


void A7129_Init(void)
{
   uint16_t tmp = 0;
   A7129_GpioInit();
   
   A7129_StrobeCmd(CMD_STBY);
   tmp = A7129_ReadReg(SYSTEMCLOCK_REG);
   //if(tmp != A7129Config[SYSTEMCLOCK_REG])
   {
      A7129_InitRf();	
   }   
   A7129_WriteReg(PLL1_REG,0x0A21);
   A7129_WriteReg(PLL2_REG,0xD605);
   delay_1ms(10);
   A7129_StrobeCmd(CMD_RFR);		//RX FIFO address pointer reset
   
   A7129_StrobeCmd(CMD_PLL);
   A7129_StrobeCmd(CMD_RX);
}
void A7129_MainLoop(void)
{
    uint8_t status, *pt;
    
      uint16_t m = A7129_ReadReg(MODE_REG);
      if(!(m&0x8))
      {
         if((pt = A7129_RxPacket(&status))!=(uint8_t *)0)
         {
            if(((pt[0]==0x99)&&(pt[1]==0x82)&&(pt[2]==0xc0)&&(pt[3]==0x53))||\
            ((pt[0]==0x2e)&&(pt[1]==0x83)&&(pt[2]==0xc0)&&(pt[3]==0x1b))||\
            ((pt[0]==0x99)&&(pt[1]==0x82)&&(pt[2]==0x8)&&(pt[3]==0xb))||\
            ((pt[0]==0x2e)&&(pt[1]==0x83)&&(pt[2]==0x4)&&(pt[3]==0x82))||\
            ((pt[0]==0x99)&&(pt[1]==0x82)&&(pt[2]==0x20)&&(pt[3]==0xae))||\
            ((pt[0]==0x2e)&&(pt[1]==0x83)&&(pt[2]==0x1)&&(pt[3]==0xd2))||\
            ((pt[0]==0x30)&&(pt[1]==0x17)&&(pt[2]==0xc0)&&(pt[3]==0x97))||\
            ((pt[0]==0x30)&&(pt[1]==0x17)&&(pt[2]==0x4)&&(pt[3]==0xe))||\
            ((pt[0]==0x0)&&(pt[1]==0x1e)&&(pt[2]==0xa7)&&(pt[3]==0x77)))
            {
                return;
            }
            else
            {
               //gd_printf(("--%x-%x-%x-%x-%x-%x-%x-%x-%x-%x\r\n",pt[0],pt[1],pt[2],pt[3],pt[4],pt[5],pt[6],pt[7],pt[8],pt[9]));
            }
            if(status==1)
            {
               sub_dev_input_handle(pt);
            }
            
             //data is valid
             
         }
         A7129_StrobeCmd(CMD_RX);
         
      }
      
     /*if(rf_int_flag)
     {
        rf_int_flag=0;
        if((pt = A7129_RxPacket(&status))!=(uint8_t *)0)
        {
           // if((pt[0]==0xb1)&&(pt[1]==0x10))
            gd_printf(("--%x-%x-%x-%x-%x-%x-%x\r\n",pt[0],pt[1],pt[2],pt[3],pt[4],pt[5],pt[6]));
            //data is valid
            
        }
        A7129_StrobeCmd(CMD_RX);
     }*/
   
}
